/**
 * @constructor
 * @class Toolbar
 * @extends GUIComponent
 */
FNIToolbar = Class.create(GUIComponent,
/**
 * @scope FNIToolbar.prototype
 */
{
  /**
   * Constructor
   * 
   * @param {Class}
   *          $super superclass
   * @param {Hash}
   *          options options
   */
  initialize : function($super, options) {
    $super(options);
    this.domNode = new Element("div", {
      className : "fniToolbar"
    });
    this.handle = new Element("div");
  },
  /**
   * Component deinitialization.
   * 
   * @param {Class}
   *          $super superclass
   */
  deinitialize : function($super) {
    $super();
  },
  /**
   * Adds a buttongroup to the toolbar
   * 
   * @param {FNIButtonGroup}
   *          buttonGroup
   */
  addButtonGroup : function(buttonGroup) {
    this.addGUIComponent(this, buttonGroup);
  },
  /**
   * Adds a separator to the toolbar
   */
  addSeparator : function() {
   this.addGUIComponent(this, new FNIToolbarSeparator({}));
  }
});

FNIToolbarSeparator = Class.create(GUIComponent,
/**
 * @scope FNIButtonGroup.prototype
 */
{
  /**
   * Constructor
   * 
   * @param {Class}
   *          $super superclass
   * @param {Hash}
   *          options options
   */
  initialize : function($super, options) {
    $super(options);
    this.domNode = new Element("div", {
      className : "fniToolbarSeparator"
    });
  },
  /**
   * Component deinitialization.
   * 
   * @param {Class}
   *          $super superclass
   */
  deinitialize : function($super) {
    $super();
  }
});

/**
 * @constructor
 * @class Base class for all buttons
 * @extends GUIComponent
 */
FNIButton = Class.create(GUIComponent, 
/**
  * @scope FNIButton.prototype
  */
{
  /**
   * Constructor
   * 
   * @param {Object}
   *          $super superclass
   * @param {Hash}
   *          options
   * @config {String} text Button text
   */
  initialize : function($super, options) {
    $super(options);
    this.domNode = new Element("div", {
      className: 'fniButton'
    });

    this._mouseOverListener = this._onMouseOver.bindAsEventListener(this);
    this._mouseOutListener = this._onMouseOut.bindAsEventListener(this);

    Event.observe(this.domNode, 'mouseover', this._mouseOverListener);
    Event.observe(this.domNode, 'mouseout', this._mouseOutListener);
    Event.observe(this.domNode, 'mouseout', this._mouseOutListener);

    this.disabled = false;
    if (!Object.isUndefined(options.text))
      this.domNode.innerHTML = options.text;
  },
  /**
   * Disables or enables button
   * 
   * @param {Boolean}
   *          disabled
   */
  setDisabled : function(disabled) {
    if (this.disabled != disabled) {
      this.disabled = disabled;
      if (this.disabled == true) {
        this.domNode.addClassName('fniButtonDisabled');
        Event.stopObserving(this.domNode, 'mouseover', this._mouseOverListener);
        Event.stopObserving(this.domNode, 'mouseout', this._mouseOutListener);
      } else {
        this.domNode.removeClassName('fniButtonDisabled');
        Event.observe(this.domNode, 'mouseover', this._mouseOverListener);
        Event.observe(this.domNode, 'mouseout', this._mouseOutListener);
      }
    }
  },
  /**
   * Deinitializes component
   * 
   * @param {Class}
   *          $super superclass
   */
  deinitialize : function($super) {
    Event.stopObserving(this.domNode, 'mouseover', this._mouseOverListener);
    Event.stopObserving(this.domNode, 'mouseout', this._mouseOutListener);
    $super();
  },
  setTooltip : function(text) {
    this.domNode.setAttribute("title", text);
  },
  setImage : function(url) {
    this.domNode.setStyle({
      backgroundImage : "url(" + url + ")"
    });
  },
  /**
   * @private
   */
  _onMouseOver : function(event) {
    this.domNode.addClassName('fniButtonMouseOver');
  },
  /**
   * @private
   */
  _onMouseOut : function(event) {
    this.domNode.removeClassName('fniButtonMouseOver');
  }
});
/**
 * @constructor
 * @class FNIToggleableButton is a button which has an ability to stay down. But it doesnt do it with a mouse click, you should you FNIToggleButton for that
 *        instead.
 * @extends FNIButton
 */
FNIToggleableButton = Class.create(FNIButton,
/**
 * @scope FNIToggleableButton.prototype
 */
{
  /**
   * Constructor
   * 
   * @param {Class}
   *          $super superclass
   * @param {Hash}
   *          options options
   */
  initialize : function($super, options) {
    $super(options);
    this.buttonDown = false;
    this._buttonClickListener = this._onButtonClick.bindAsEventListener(this);
    Event.observe(this.domNode, "click", this._buttonClickListener);
  },
  /**
   * Component deinitialization.
   * 
   * @param {Class}
   *          $super superclass
   */
  deinitialize : function($super) {
    Event.stopObserving(this.domNode, 'click', this._buttonClickListener);
    $super();
  },
  isButtonDown : function() {
    return this.buttonDown;
  },
  /**
   * sets button up or down
   * 
   * @param {Boolean}
   *          buttonDown
   */
  setButtonDown : function(buttonDown) {
    if (this.buttonDown != buttonDown) {
      this.buttonDown = buttonDown;
      if (this.buttonDown) {
        this.domNode.addClassName('fniButtonDown');
        this.fire("buttonDown", {});
      } else {
        this.domNode.removeClassName('fniButtonDown');
        this.fire("buttonUp", {});
      }
    }
  },
  /**
   * @private
   */
  _onButtonClick : function(event) {
    this.fire("buttonClick", {});
  }
});
/**
 * @constructor
 * @class Normal push button
 * @extends FNIButton
 */
FNIPushButton = Class.create(FNIButton,
/**
 * @scope FNIPushButton.prototype
 */
{
  /**
   * Constructor
   * 
   * @param {Class}
   *          $super superclass
   * @param {options}
   *          options options
   */
  initialize : function($super, options) {
    $super(options);

    this._mouseDownListener = this._onMouseDown.bindAsEventListener(this);
    this._mouseUpListener = this._onMouseUp.bindAsEventListener(this);
    this.__mouseOutListener = this.__onMouseOut.bindAsEventListener(this);
    Event.observe(this.domNode, 'mouseout', this.__mouseOutListener);
    Event.observe(this.domNode, 'mousedown', this._mouseDownListener);
    Event.observe(this.domNode, 'mouseup', this._mouseUpListener);
  },
  /**
   * Component deinitialization.
   * 
   * @param {Class}
   *          $super superclass
   */
  deinitialize : function($super) {
    Event.stopObserving(this.domNode, 'mousedown', this._mouseDownListener);
    Event.stopObserving(this.domNode, 'mouseup', this._mouseUpListener);
    Event.stopObserving(this.domNode, 'mouseout', this.__mouseOutListener);
    $super();
  },
  /**
   * @private
   */
  _onMouseDown : function(event) {
    if (this.disabled == false) {
      this.mouseDown = true;
      this.domNode.addClassName('fniButtonDown');
    }
  },
  /**
   * @private
   */
  _onMouseUp : function(event) {
    this.domNode.removeClassName('fniButtonDown');
    if (this.mouseDown == true) {
      this.mouseDown = false;
      this.fire('buttonClick', {});
    }
  },
  /**
   * @private
   */
  __onMouseOut : function(event) {
    this.domNode.removeClassName('fniButtonDown');
    this.mouseDown = false;
  }
});
/**
 * @constructor
 * @class Button group
 * @extends GUIComponent
 */
FNIButtonGroup = Class.create(GUIComponent,
/**
 * @scope FNIButtonGroup.prototype
 */
{
  /**
   * Constructor
   * 
   * @param {Class}
   *          $super superclass
   * @param {Hash}
   *          options options
   */
  initialize : function($super, options) {
    $super(options);
    this.domNode = new Element("div", {
      className: 'fniButtonGroup'
    });

    this._mode = options.mode||FNIButtonGroup.MODE_NORMAL;
    this._buttons = new Array();
  },
  /**
   * Component deinitialization.
   * 
   * @param {Class}
   *          $super superclass
   */
  deinitialize : function($super) {
    $super();
  },
  /**
   * 
   * @param {FNIButton}
   *          button adds a button to the group
   */
  addButton : function(button) {
    this.addGUIComponent(this, button);
    button.addListener("buttonClick", this, this._onButtonClick);
    this._buttons.push(button);
  },
  /**
   * Returns group buttons as Array
   * 
   * @return {Array}
   */
  getButtons : function() {
    return this._buttons;
  },
  /**
   * @private
   */
  _onButtonClick : function(event) {
    switch (this._mode) {
    case FNIButtonGroup.MODE_SINGLEDOWN:
      for ( var i = 0; i < this._buttons.length; i++) {
        if (this._buttons[i] != event.component)
          this._buttons[i].setButtonDown(false);
      }
      event.component.setButtonDown(true);
      break;
    case FNIButtonGroup.MODE_MULTIDOWN:
      break;
    }

    this.fire("buttonClick", {
      button : event.component
    });
  }
});

Object.extend(FNIButtonGroup, {
  /**
   * Normal mode, where group doesnt do anything at all to buttons inside it
   */
  MODE_NORMAL : 0,
  /**
   * Singledown mode, where only one button can be down at the same time. In this mode all buttons should be instances of FNIToggleableButton
   */
  MODE_SINGLEDOWN : 1,
  /**
   * Multidown mode, which works just like normal mode, with a exception that button objects should be instances of FNIToggleButtons.
   */
  MODE_MULTIDOWN : 2
});
/**
 * @constructor
 * @class
 * @extends FNIPushButton
 */
FNIColorButton = Class.create(FNIPushButton,
/**
 * @scope FNIColorButton.prototype
 */
{
  /**
   * Constructor
   * 
   * @param {Class}
   *          $super superclass
   * @param {options}
   *          options options
   */
  initialize : function($super, options) {
    $super(options);

    this._colorView = new Element("div");
    this.domNode.appendChild(this._colorView);
    this._colorView.addClassName('fniColorButtonColorView');

    if (options.color)
      this.setColor(options.color);
  },
  /**
   * Component deinitialization.
   * 
   * @param {Class}
   *          $super superclass
   */
  deinitialize : function($super) {
    $super();
  },
  /**
   * Sets button color
   * 
   * @param {Object}
   *          color color in hex values (#rrggbb)
   */
  setColor : function(color) {
    this._colorView.style.backgroundColor = color;
  }
});
/**
 * @constructor
 * @class Toggle button
 * @extends FNIToggleableButton
 */
FNIToggleButton = Class.create(FNIToggleableButton,
/**
 * @scope FNIToggleButton.prototype
 */
{
  /**
   * Constructor
   * 
   * @param {Class}
   *          $super superclass
   * @param {Hash}
   *          options options
   */
  initialize : function($super, options) {
    $super(options);
    this.buttonDown = false;
    this.addListener("buttonClick", this, this._onButtonClick);
  },
  /**
   * @private
   */
  _onButtonClick : function() {
    this.setButtonDown(!this.isButtonDown());
  }
});